﻿using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using BPM.Base.WFLib;
using System.Workflow.Runtime.Tracking;
using System.Workflow.Runtime.Hosting;
using System;
using BPM.Base.Tools;
using BPM.Foundation.WFDB;

namespace BPM.Foundation.WFService
{
    public partial interface IWorkflowService
    {
        [System.ServiceModel.OperationContract]
        int? startRuntime(string pid);

        [System.ServiceModel.OperationContract]
        int? stopRuntime(string pid);

        [System.ServiceModel.OperationContract]
        List<Guid> getWorkflowInstanceFromRuntime(string pid);
    }


    public partial class WorkflowService : IWorkflowService
    {
        
        WorkflowRuntime runtime;//工作流引擎

        
        ExternalDataExchangeService exchange;//通信服务

        
        ExternalEvent externalEvent;//外部事件触发器

        
        SqlTrackingService tracking;//跟踪服务
      
        
        SqlWorkflowPersistenceService persistence;//持久化服务
     
        //[4.1	启动引擎]
        public int? startRuntime(string pid)
        {

            try
            {
                if (runtime == null)
                {
                    //[1.1]
                    string trackingConnectionString = MyConfig.getConnection("trackingConnectionString");
                    string persistenceConnectionString = MyConfig.getConnection("persistenceConnectionString");
                    if (string.IsNullOrEmpty(trackingConnectionString) || string.IsNullOrEmpty(persistenceConnectionString))
                        return -1;

                    //[1.2]
                    runtime = new WorkflowRuntime();

                    //[1.3]通信
                    exchange = new ExternalDataExchangeService();
                    externalEvent = new ExternalEvent();
                    runtime.AddService(exchange);
                    exchange.AddService(externalEvent);

                    //[1.4]持久化
                    TimeSpan locktime = new TimeSpan(0, 10, 0);
                    TimeSpan loadtime = new TimeSpan(0, 5, 0);
                    persistence = new SqlWorkflowPersistenceService(persistenceConnectionString, true, locktime, loadtime);
                    runtime.AddService(persistence);

                    // 注释掉本段代码的原因是如果加上了跟踪,好像所有的工作流实例都会在启动后自动结束,提交事件时会报错,因此先注释掉
                    //[1.5]跟踪
                    tracking = new SqlTrackingService(trackingConnectionString);
                    runtime.AddService(tracking);

                    //[1.6]
                    runtime.AddService(this);


                    //[1.7]
                    this.runtime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(runtime_WorkflowCompleted);
                    this.runtime.Started += new EventHandler<WorkflowRuntimeEventArgs>(runtime_Started);
                    this.runtime.Stopped += new EventHandler<WorkflowRuntimeEventArgs>(runtime_Stopped);
                    this.runtime.ServicesExceptionNotHandled += new EventHandler<ServicesExceptionNotHandledEventArgs>(runtime_ServicesExceptionNotHandled);
                    this.runtime.WorkflowAborted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowAborted);
                    this.runtime.WorkflowCreated += new EventHandler<WorkflowEventArgs>(runtime_WorkflowCreated);
                    this.runtime.WorkflowIdled += new EventHandler<WorkflowEventArgs>(runtime_WorkflowIdled);
                    this.runtime.WorkflowLoaded += new EventHandler<WorkflowEventArgs>(runtime_WorkflowLoaded);
                    this.runtime.WorkflowPersisted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowPersisted);
                    this.runtime.WorkflowResumed += new EventHandler<WorkflowEventArgs>(runtime_WorkflowResumed);
                    this.runtime.WorkflowStarted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowStarted);
                    this.runtime.WorkflowSuspended += new EventHandler<WorkflowSuspendedEventArgs>(runtime_WorkflowSuspended);
                    this.runtime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(runtime_WorkflowTerminated);
                    this.runtime.WorkflowUnloaded += new EventHandler<WorkflowEventArgs>(runtime_WorkflowUnloaded);

                    //[1.8]
                    runtime.StartRuntime();

                    //[1.9]
                    MyLog.writeInfo("工作流引擎成功启动与:" + System.DateTime.Now.ToString());

                    return null;
                }
                else
                {
                    if (runtime.IsStarted)
                    {
                        //[-1.1]
                        return 1;
                    }
                    else
                    {
                        //[-1.-1.1]
                        runtime.StartRuntime();

                        //[-1.-1.2]
                        MyLog.writeInfo("工作流引擎重新启动与:" + System.DateTime.Now.ToString());

                        return null;
                    }
                }
            }
            catch (System.Exception ex)
            {
                //[1.10]
                MyLog.writeError("工作流引擎启动时出错:" + ex.Message);
                return -2;
            }
        }

        //[4.2	停止引擎]
        public int? stopRuntime(string pid)
        {
            if (runtime != null && runtime.IsStarted)
            {
                //[1.1]
                runtime.StopRuntime();
                //[1.2]
                MyLog.writeInfo("工作流引擎停止:" + System.DateTime.Now.ToString());
                return null;
            }
            else
            {
                //[-1.1]
                MyLog.writeInfo("工作流引擎已经停止，与" + System.DateTime.Now.ToString() + "又调用停止引擎方法！");
                return 1;
            }
        }

        //[4.3	清除状态信息]
        public int? clearStateInfo(string pid, int testID)
        {
            using (WFDBDataContext wfDB = new WFDBDataContext(MyConfig.getConnection("myconstring")))
            {
                //[0]代表成功；[1]代表失败
                return wfDB.clearInstanceInfo(testID);
            }
        }

        //[4.4	得到引擎中的实例]
        public List<Guid> getWorkflowInstanceFromRuntime(string pid)
        {
            //[1]
            List<Guid> workflowInMemory = new List<Guid>();
            foreach (var workflowInstance in runtime.GetLoadedWorkflows().ToList())
            {
                workflowInMemory.Add(workflowInstance.InstanceId);
            }

            //[2]
            List<Guid> workflowInDB = new List<Guid>();
            foreach (var workflowInDBDescription in persistence.GetAllWorkflows().ToList())
            {
                workflowInDB.Add(workflowInDBDescription.WorkflowInstanceId);
            }

            //[3]
            List<Guid> workflowInstanceses = workflowInMemory.Union(workflowInDB).ToList();

            return workflowInstanceses;
        }
    }
}
